<template>
  <div class="panel-template font-container">
    <div class="title">文字</div>
    <div class="content">
      <div class="block">
        <div class="dt">样式</div>
        <div class="dd">
          <!-- 文字颜色 -->
          <div class="panel-row">
            <dl class="color">
              <dt>颜色</dt>
              <dd>
                <el-color-picker
                  class="panel-color-picker"
                  popper-class="color-picker-button-hidden"
                  color-format="hex"
                  show-alpha
                  :predefine="predefineColors"
                  :class="{ more: colorType === 'object' }"
                  v-model="color"
                  @active-change="onChangeColor"
                />
              </dd>
            </dl>
          </div>
          <div class="panel-row">
            <dl class="color">
              <dt>背景色</dt>
              <dd>
                <el-color-picker
                  class="panel-color-picker"
                  popper-class="color-picker-button-hidden"
                  color-format="hex"
                  show-alpha
                  :predefine="predefineColors"
                  :class="{ more: backgroundType === 'object' }"
                  v-model="backgroundColor"
                  @active-change="onChangeBackgroundColor"
                />
              </dd>
            </dl>
          </div>
        </div>
      </div>
      <div class="block">
        <div class="dt">文字</div>
        <div class="dd">
          <!-- 字体设置 -->
          <div class="font-family">
            <el-select
              popper-class="popper-font-family"
              placeholder="请选择字体"
              :class="familyClass"
              v-model="family"
              @change="onChangeFont"
            >
              <el-option
                v-for="item of familyList"
                :key="item.value"
                :label="item.name"
                :value="item.value"
              >
                <span :class="item.value + '-svg'">{{item.name}}</span>
              </el-option>
            </el-select>
          </div>
          <!-- 大小设置 -->
          <div class="panel-row">
            <dl class="font-size">
              <dt>字号</dt>
              <dd>
                <el-slider
                  :min="12"
                  :max="400"
                  v-model="size"
                  @input="onChangeSize"
                />
              </dd>
            </dl>
          </div>
          <!-- 基本设置 -->
          <ul class="panel-row">
            <li>
              <el-button icon="iconfont icon-014" :class="{active: getFormat.bold}" @click="setBold"></el-button>
            </li>
            <li>
              <el-button icon="iconfont icon-015" :class="{active: getFormat.italic}" @click="setItalic"></el-button>
            </li>
            <li>
              <el-button icon="iconfont icon-016" :class="{active: getFormat.underline}" @click="setUnderline"></el-button>
            </li>
            <li>
              <el-button icon="iconfont icon-017" :class="{active: getFormat.strike}" @click="setStrike"></el-button>
            </li>
          </ul>
          <!-- 间距设置 -->
          <ul class="panel-row">
            <li>
              <el-button :icon="getAlign.icon" @click="setAlign" />
            </li>
            <li>
              <el-popover placement="bottom" trigger="hover" width="240" popper-class="popper-panel-row">
                <dl class="slider">
                  <dt>字间距</dt>
                  <dd>
                    <el-slider v-model="spacing" :max="90" @input="onChangeSpacing"></el-slider>
                  </dd>
                </dl>
                <el-button slot="reference" icon="iconfont icon-022"></el-button>
              </el-popover>
            </li>
            <li>
              <el-popover placement="bottom" trigger="hover" width="240" popper-class="popper-panel-row">
                <dl class="slider">
                  <dt>行间距</dt>
                  <dd>
                    <el-slider v-model="line" :step="0.1" :max="5" @input="onChangeLine"></el-slider>
                  </dd>
                </dl>
                <el-button slot="reference" icon="iconfont icon-023"></el-button>
              </el-popover>
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import { STORE_NAMESPACE } from '../../../../config/constants'
export default {
  name: 'DesignPanelFont',
  data () {
    return {
      align: [{ // 对齐样式
        name: '',
        icon: 'iconfont icon-018'
      }, {
        name: 'center',
        icon: 'iconfont icon-019'
      }, {
        name: 'right',
        icon: 'iconfont icon-020'
      }, {
        name: 'justify',
        icon: 'iconfont icon-021'
      }],
      familyList: [{ // 字体样式
        name: '思源黑体-极细',
        value: 'SourceHanSansCN-01'
      }, {
        name: '思源黑体-纤细',
        value: 'SourceHanSansCN-02'
      }, {
        name: '思源黑体-常规',
        value: 'SourceHanSansCN-03'
      }, {
        name: '思源黑体-粗体',
        value: 'SourceHanSansCN-04'
      }, {
        name: '思源黑体-中等',
        value: 'SourceHanSansCN-05'
      }, {
        name: '思源黑体-中粗',
        value: 'SourceHanSansCN-06'
      }, {
        name: '思源黑体-特粗',
        value: 'SourceHanSansCN-07'
      }],
      predefineColors: ['#000000', '#737373', '#D9D9D9', '#FFFFFF', '#A82B2A', '#A86F0E', '#528725', '#191F8B', '#49188B', '#E70B18'], // 常用颜色
      family: 'SourceHanSansCN-03', // 字体
      colorType: null, // 颜色类型
      backgroundType: null, // 背景色类型
      color: '#000',
      backgroundColor: '#fff',
      size: 15, // 字号
      line: null, // 行间距
      spacing: null, // 字间距
      range: null, // 当前选中的文字, { index, length }
      oldRange: null, // 之前选中的文字, { index, length }
    }
  },
  computed: {
    ...mapState({
      editor: state => state[STORE_NAMESPACE].currentEditor,
      current: state => state[STORE_NAMESPACE].current,
      currentIndex: state => state[STORE_NAMESPACE].currentIndex
    }),
    // 动态更新选中的文字
    getRange () {
      const range = this.range || {}
      const index = range.index || 0
      const length = range.length === undefined ? (this.editor ? this.editor.getLength() : 0) : range.length
      return {
        index,
        length
      }
    },
    // 获取文本样式
    getFormat () {
      const { index, length } = this.getRange
      return this.editor ? this.editor.getFormat(index, length) : {} // getFormat 返回编辑器某一段的样式
    },
    // 获取当前对齐样式
    getAlign () {
      const { align } = this.editor ? this.editor.getFormat() : {}
      if (align) {
        return this.align.find(item => item.name === align)
      } else {
        return {
          name: '',
          icon: 'iconfont icon-018'
        }
      }
    },
    // 获取字体样式
    familyClass () {
      if (this.family) {
        return this.family + '-select'
      } else {
        return ''
      }
    }
  },
  watch: {
    editor (val) {
      val && this.initEditorOn()
    }
  },
  methods: {
    // 设置当前选中块
    setCurrent (current) {
      this.$store.dispatch(`${STORE_NAMESPACE}/setCurrent`, current)
      this.$store.dispatch(`${STORE_NAMESPACE}/setElement`, {
        index: this.currentIndex,
        value: current
      })
    },
    // 初始化编辑器事件
    initEditorOn () {
      // 解绑之前的事件
      this.editor.off('selection-change', this.onSelectionChange)
      // 注册新的事件
      this.editor.on('selection-change', this.onSelectionChange)
      // 设置初始属性
      this.initAttr()
      // 字间距
      this.spacing = this.current.style['letter-spacing']
      // 行间距
      this.line = this.current.style['line-height']
      // 字体
      this.family = this.current.style['font-family']
    },
    // 字体选中事件回调
    onSelectionChange (range, oldRange, source) {
      console.log(range, oldRange, source)
      this.range = range
      this.oldRange = oldRange
      this.editor.getFormat() // 编码过程中存在失去焦点导致range为null的情况, 通过调用getFormat()这个api, 不带参数将使用用户当前的选择范围, 实际上就是把oldRange给返回了回来, 所以这里的过程其实是先range为null, 后range为正常数值, 这里不用调用, 在计算属性getAlign中隐性调用了
      this.initAttr()
    },
    // 文字初始化属性
    initAttr () {
      const { color, background, size } = this.getFormat
      // 字体色
      this.color = color || '#000'
      this.colorType = typeof color
      if (this.colorType === 'object') {
        this.color = '#fff'
      }
      // 背景色
      this.backgroundColor = background || '#fff'
      this.backgroundType = typeof background
      if (this.backgroundType === 'object') {
        this.backgroundColor = '#fff'
      }
      // 字号
      if (typeof size === 'string') {
        this.size = parseInt(size)
      }
    },
    // 设置选中字体样式
    formatText (format, value) {
      const { index, length } = this.getRange
      const end = (index === length) && length === 0 ? this.editor.getLength() : length
      this.editor.formatText(index, end, format, value) // https://quilljs.com/docs/api/#formattext
    },
    // 设置全局字体样式
    setFormat (format, value) {
      this.editor.format(format, value)
    },
    // 设置颜色
    onChangeColor (color) {
      this.color = color
      this.formatText('color', color)
    },
    // 设置背景色
    onChangeBackgroundColor (color) {
      this.backgroundColor = color
      this.formatText('background', color)
    },
    // 字体设置
    onChangeFont (value) {
      const current = {
        ...this.current,
        style: {
          ...this.current.style,
          'font-family': value
        }
      }
      this.setCurrent(current)
      this.editor && this.getEditorInfo()
    },
    // 字号设置
    onChangeSize (value) {
      if (this.editor) {
        const { index, length } = this.getRange
        // this.editor.formatText(index, length, 'size', `${value}px`)
        this.formatText('size', `${value}px`)
      }
    },
    // 加粗
    setBold () {
      const { bold } = this.getFormat
      this.formatText('bold', !bold)
    },
    // 斜体
    setItalic () {
      const { italic } = this.getFormat
      this.formatText('italic', !italic)
    },
    // 下划线
    setUnderline () {
      const { underline } = this.getFormat
      this.formatText('underline', !underline)
    },
    // 删除线
    setStrike () {
      const { strike } = this.getFormat
      this.formatText('strike', !strike)
    },
    // 对齐
    setAlign () {
      const { name } = this.getAlign
      let index = this.align.findIndex(item => item.name === name) || 0
      index++
      if (index === this.align.length) {
        index = 0
      }
      this.setFormat('align', this.align[index].name)
    },
    // 字间距
    onChangeSpacing (value) {
      if (this.current) {
        const current = {
          ...this.current,
          style: {
            ...this.current.style,
            'letter-spacing': value
          }
        }
        this.setCurrent(current)
        this.editor && this.getEditorInfo()
      }
    },
    // 行间距
    onChangeLine (value) {
      if (this.current) {
        const current = {
          ...this.current,
          style: {
            ...this.current.style,
            'line-height': value
          }
        }
        this.setCurrent(current)
        this.editor && this.getEditorInfo()
      }
    },
    // 更新编辑器
    getEditorInfo () {
      const { clientWidth, clientHeight } = this.editor.root
      const current = {
        ...this.current,
        width: clientWidth + 1,
        height: clientHeight + 1
      }
      this.setCurrent(current)
    }
  }
}
</script>

<style lang="less" scoped>
.font-container {
  .ql-toolbar {
    border: 0;
    padding: 0;
  }
  .panel-color-picker {
    display: block;
    padding-right: 10px;
    height: 22px;
    ::v-deep .el-icon-arrow-down,
    ::v-deep .el-icon-close {
      display: none;
    }
    ::v-deep .el-color-picker__color {
      border-color: #f1f1f1;
      border-radius: 3px;
      overflow: hidden;
    }
    ::v-deep .el-color-picker__trigger {
      padding: 0;
      border: 0;
      width: 100%;
      height: 22px;
      &.more {
        position: relative;
        &:after {
          position: absolute;
          content: '多种颜色';
          pointer-events: none;
          left: 0;
          top: 50%;
          width: 100%;
          transform: translate3d(0, -50%, 0);
          color: #666;
          text-align: center;
          font-size: 12px;
        }
      }
    }
  }
  .font-family {
    margin-bottom: 10px;
    .el-select {
      display: block;
      & ::v-deep .el-input__inner {
        color: #000;
      }
      &.SourceHanSansCN-01-select ::v-deep .el-input__inner { font-family: 'SourceHanSansCN-01' !important; }
      &.SourceHanSansCN-02-select ::v-deep .el-input__inner { font-family: 'SourceHanSansCN-02' !important; }
      &.SourceHanSansCN-03-select ::v-deep .el-input__inner { font-family: 'SourceHanSansCN-03' !important; }
      &.SourceHanSansCN-04-select ::v-deep .el-input__inner { font-family: 'SourceHanSansCN-04' !important; }
      &.SourceHanSansCN-05-select ::v-deep .el-input__inner { font-family: 'SourceHanSansCN-05' !important; }
      &.SourceHanSansCN-06-select ::v-deep .el-input__inner { font-family: 'SourceHanSansCN-06' !important; }
      &.SourceHanSansCN-07-select ::v-deep .el-input__inner { font-family: 'SourceHanSansCN-06' !important; }
    }
    .el-input--medium .el-input__inner {
      height: 40px;
      line-height: 40px;
    }
  }
  .font-size {
    padding: 4px 20px 4px 0;
    .el-slider {
      .el-slider__runway {
        margin: 0;
      }
    }
  }
}
</style>